home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
misc
/
amag
/
AM9403_2.lha
/
tips & tricks
/
wurzel.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-21
|
3KB
|
81 lines
; Dieses Programm berechnet die Wurzel eines
; 32-Bit-Unsigned-Integer-Ausdrucks (d.h. bis
; max. 4.294.967.295) per Intervallhalbierung.
; Ergebnis=SQRT(n) aufgerundet.
; Ein- und Ausgabe:
; d0 Eingabe, bleibt erhalten
; d1 obere Grenze des Intervalls = Ergebnis
; d2 untere Grenze des Intervalls
; d3,d4 Rechenregister
; a0 Zeiger auf Wertetabelle
exakt equ 1 ; Genauigkeit (zwischen 1 und 8)
SQRT:
movem.l d2-d4/a0,-(sp) ; Register sichern
moveq #0,d2 ; untere Grenze löschen
moveq #0,d1 ; obere Grenze löschen
moveq #30,d3 ; Bit-Zähler setzen
move.l d0,d4 ; Wert in Rechenregister
beq.s sqrt_6 ; n=0 -> keine Rechnung !
swap d4 ; oberes Wort
tst.w d4 ; testen
bne.s sqrt_11 ; Sprung, wenn <> 0
moveq #14,d3 ; nur noch unteres Wort
move.w d0,d4 ; untersuchen
sqrt_11:
move.w d4,d2 ; zu untersuchendes Wort merken
and.w #$ff00,d4 ; oberen 8 Bit untersuchen
bne.s sqrt_12 ; sind gesetzt -> Sprung
subq.w #8,d3 ; 8 Bit weiter
move.w d2,d4 ; Wort nochmal holen
lsl.w #8,d4 ; unteren 8 Bit untersuchen
sqrt_12:
asl.w #1,d4 ; oberstes Bit suchen
dbcs d3,sqrt_12 ; wenn CarrySet := gefunden
add.w d3,d3 ; * 2 := auf Wortgrenze legen
; Zeiger auf Werte berechnen
lea sqrt_tab(pc,d3.w),a0
move.w (a0)+,d2 ; untere Grenze holen
move.w (a0),d1 ; obere Grenze holen
bra.s sqrt_5 ; Ende erreicht?
sqrt_2:
move.l d2,d4 ; obere Grenze und
add.l d1,d4 ; untere Grenze addieren
lsr.l #1,d4 ; Mittelwert bilden: m=(og+ug)/2
move.l d4,d3 ; m merken
mulu d4,d4 ; m quadrieren
cmp.l d0,d4 ; Test: Ist m*m > n ?
bgt.s sqrt_4 ; ja -> springen
sqrt_3: ; obere Hälfte enthält
; gesuchten Wert
move.l d3,d2 ; untere Grenze = m
bra.s sqrt_5
sqrt_4: ; untere Hälfte enthält Wert
move.l d3,d1 ; obere Grenze = m
sqrt_5:
move.l d1,d4 ; Differenz bestimmen
sub.l d2,d4 ; delta = obere - untere Grenze
subq.w #exakt,d4 ; delta = < exakt ? , Konstante
; bestimmt die Genauigkeit
; Differenz zu groß, weiterrechnen
bgt.s sqrt_2
move.l d2,d4
mulu d4,d4 ; untere Grenze quadrieren
cmp.l d4,d0 ; Vergleich mit n
bgt.s sqrt_6 ; Test, ob untere Grenze das
move.l d2,d1 ; Ergebnis ist
sqrt_6:
movem.l (sp)+,d2-d4/a0 ; Register restaurieren
rts
dc.w 0
sqrt_tab: ; Wurzel-Intervall-Grenzen | Bit
dc.w 1,2,3,4,6,8,12,16 ; 0-7
dc.w 23,32,46,64,91,128,182,256 ; 8-15
dc.w 363,512,725,1024,1449,2048,2897,4096 ; 16-23
; 24-31
dc.w 5793,8192,11586,16384,23171,32768,46341,65535